import json
import logging
from urllib.parse import urlencode, parse_qs
from urllib.request import urlopen

from django.conf import settings
from itsdangerous import TimedJSONWebSignatureSerializer as TJWSSerializer, \
    BadData

from oauth.exceptions import QQAPIError
from . import constants

logger = logging.getLogger("django")


class OAuthQQ(object):
    """QQ认证辅助工具类"""
    def __init__(self, client_id=None, client_secret=None, redirect_uri=None,
                 state=None):
        self.client_id = client_id or settings.QQ_CLIENT_ID
        self.client_secret = client_secret or settings.QQ_CLIENT_SECRET
        self.redirect_uri = redirect_uri or settings.QQ_REDIRECT_URI
        self.state = state or settings.QQ_STATE  # 用户保存登录成功后的跳转页面路径

    def get_qq_login_url(self):
        """获取qq登录的网址"""
        params = {
            "response_type": "code",
            "client_id": self.client_id,
            "redirect_uri": self.redirect_uri,
            "state": self.state,
            "scope": "get_user_info",  # 可有可无
        }
        url = "https://graph.qq.com/oauth2.0/authorize?" + urlencode(params)
        return url

    def get_access_token(self, code):
        """获取access_token"""
        params = {
            "grant_type": "authorization_code",
            "client_id": self.client_id,
            "client_secret": self.client_secret,
            "code": code,
            "redirect_uri": self.redirect_uri
        }
        url = "https://graph.qq.com/oauth2.0/token?" + urlencode(params)
        try:
            # 发送请求
            response = urlopen(url)
            # 读取响应体数据
            response_data = response.read().decode()
            # 解析对应的access_token
            data = parse_qs(response_data)
        except Exception as e:
            logger.error("获取access_token异常:%s" % e)
            raise QQAPIError
        access_token = data.get("access_token", None)  # 结果是个列表

        return access_token[0]

    def get_openid(self, access_token):
        """
        获取用户的openid
        """
        url = "https://graph.qq.com/oauth2.0/me?access_token=" + access_token
        response = urlopen(url)
        response_data = response.read().decode()
        try:
            # 返回的数据 callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} )\n;
            data = json.loads(response_data[10:-4])
        except Exception:
            data = parse_qs(response_data)
            logger.error("code=%s msg=%s" % (data.get("code"), data.get("msg")))
            raise QQAPIError
        else:
            openid = data.get("openid", None)
            return openid

    @staticmethod
    def generate_save_user_token(openid):
        """生成保存用户数据的token"""
        serializer = TJWSSerializer(settings.SECRET_KEY,
                                    constants.SAVE_QQ_USER_TOKEN_EXPIRES)
        data = {"openid": openid},
        token = serializer.dumps(data)
        return token.decode()

    @staticmethod
    def check_save_user_token(access_token):
        """
        验证access_token
        :param access_token:
        :return:
        """
        serializer = TJWSSerializer(settings.SECRET_KEY, constants.SAVE_QQ_USER_TOKEN_EXPIRES)
        try:
            data = serializer.loads(access_token)
            # print(data)
        except BadData:
            return None
        else:
            return data[0]["openid"]







